<?php

namespace app\home\service;

use app\home\model\Order;
use app\home\model\SysActivityInfo;
use app\home\model\UserGameInfo;
use app\home\model\UserPropLog;
use app\home\model\UserPropsInfo;
use app\home\model\UserScoreLog;
use think\Db;
use app\home\model\Player;

class GameProcess
{

    protected $player_field = 'UserID,Score,Diamond,ChargeScore,TotalRecharge,SMoney,RechargeTimes,VipLevel,Lottery,LotteryPool,LotteryStock,LoginServer';

    protected $player_select = [];// 玩家查询到的字段
    protected $player_update = [];// 玩家待更新的字段
    protected $props_array = [];// 待发送的游戏道具
    protected $order_select = [];// 订单查询的结果

    public function __construct($order_id, $price)
    {
        mylog('订单号:'.$order_id);
        $this->order_select = (new Order())->checkOrder($order_id, $price);

        // 订单没有异常时,查询玩家信息
        if($this->order_select != false){
            $this->player_select = (new Player())->field($this->player_field)->where('UserID', $this->order_select['userid'])->find()->toArray();
        }
    }

    public function orderProcess()
    {

        if ($this->order_select == false) {
            return false;
        }

        $billing_id = $this->order_select['goods_id'];
        $order_id = $this->order_select['id'];
        $UserID = $this->order_select['userid'];

        // 防止出现计费点找不到的情况
        $billing_point_array = $this->getBillingPoint($billing_id);
        if (empty($billing_point_array)) {
            mylog('billing_point not found');
            return false;
        }

        // 只允许计费点类型1000
        if ($billing_point_array['Type'] != 1000) {
            mylog($billing_id . ' not found');
            return false;
        }

        // 计费点的价格配置可能有异常
        if (!isset($billing_point_array['Price']) || !is_numeric($billing_point_array['Price'])) {
            mylog($billing_id . ' Price invalid');
            return false;
        }

        // 特殊处理比例不是1比10的情况
        if(isset($billing_point_array['SMoney'])){
            $SMoney = $billing_point_array['SMoney'];
        }else{
            $SMoney = $billing_point_array['Price'] * 10;
        }

        array_push($this->props_array, [3, $SMoney, 0]);

        /*充值赢大礼*/
        $this->Recharge_wins_big_gifts($UserID, $billing_point_array['Price'], $billing_id);

        /*充值道具活动*/
        $item_arr = $this->Recharge_item_recharge_activity($UserID, $billing_point_array['Price']);
        if (!empty($item_arr)) {
            $this->props_array = array_merge($this->props_array, $item_arr);
        }

        /*处理Vip等级*/
        $this->processVipLevel();
        // 开启事务
        try {
            $db = Db::connect('db_config2');
            $db->startTrans();
        } catch (\Exception $e) {
            mylog($e->getMessage());
            return false;
        }

        try {

            $time = date('Y-m-d H:i:s');

            $data['status'] = 1;
            $data['paydate'] = $time;

            if ((new Order())->save($data, ['id' => $order_id]) == false) {
                throw new \Exception('Order rollback');
            }

            $this->player_update['ChargeScore'] = $this->player_select['ChargeScore'] + $billing_point_array['Price'];
            $this->player_update['TotalRecharge'] = $this->player_select['TotalRecharge'] + $billing_point_array['Price'];
            $this->player_update['RechargeTimes'] = $this->player_select['RechargeTimes'] + 1;
            $this->player_update['SMoney'] = $this->player_select['SMoney'] + $SMoney;

            if ((new Player())->save($this->player_update, ['UserID' => $UserID]) == false) {
                throw new \Exception('Order rollback');
            }

            $db->commit();

            /*向游戏服务器发送充值消息*/
            if ($this->get_curl_type($UserID,$this->props_array) == false) {
                mylog('通知服务器失败');
            }

            $this->Recharge_score_log();

            // 把充值总额写入到有序集合
            $redis = new \Redis();

            $redis->connect(config('REDIS_FORMAL.host'), config('REDIS_FORMAL.port'));
            $redis->auth(config('REDIS_FORMAL.auth'));
            $redis->select(0);
            $time = date("Ymd");
            $redis->zIncrBy('recharge_' . $time, $billing_point_array['Price'], $UserID);
            $month = date("Ym");
            $redis->zIncrBy('final_rank_month_' . $month, $billing_point_array['Price']*100, $UserID);

            mylog('订单处理ok');

            return 'success';
        } catch (\Exception $e) {
            mylog($e->getMessage());
            $db->rollback();
            return false;
        }
    }

    protected function getBillingPoint($billing_id)
    {
        $json_string = file_get_contents(env('PLATFORM.BillingPoint'));
        $data = json_decode($json_string, true);
        return isset($data[$billing_id]) ? $data[$billing_id][0] : null;
    }


    protected function processVipLevel()
    {
        // var_dump($this->player_select['TotalRecharge']);
        // var_dump($this->order_select['amount']);
        // die;
        $level = vip_level($this->player_select['TotalRecharge'] + $this->order_select['amount']);   //充值后对应等级
        // 充值前的vip<2 充值后的vip>=2 鱼券奖池 -= 当前身上的金币
        if ($this->player_select['VipLevel'] < 2 && $level >= 2) {
            $this->player_update['LotteryPool'] = $this->player_select['LotteryPool'] - $this->player_select['Score'];
        }

        if ($level > $this->player_select['VipLevel']) {
            $this->player_update['VipLevel'] = $level;
        }

        return true;
    }

    /**
     * 通知游戏服务器
     * @param $UserID
     * @param array $dataArray
     * @return string   success
     * @throws \think\Exception
     */
    protected function get_curl_type($UserID, $dataArray = [])
    {
        $cannon = (new UserGameInfo)->where('UserID', $UserID)->value('Cannon');
        $data = [
            'Type' => 1000,
            'RechargeStock' => 0,
            'Award' => $dataArray,
            'UserID' => $UserID,
            'Cannon' => $cannon,
            'Score' => $this->player_select['Score'],
            'Diamond' => $this->player_select['Diamond'],
            'GoodsID' => $this->order_select['goods_id'],
            'channel_id' => $this->order_select['channel_id'],
            'amount' => $this->order_select['amount'],
            'SMoney' => $this->player_update['SMoney'],
            'Recharge' => $this->player_update['TotalRecharge'],
            'VipLevel' => isset($this->player_update['VipLevel'])?$this->player_update['VipLevel']:$this->player_select['VipLevel'],
        ];
        $url_param = json_encode($data);
        $url = getServerUrl($this->player_select['LoginServer']) . '?id=1&data=' . $url_param;

        file_put_contents('server_data.txt', date('[Y-m-d H:i:s]') . ' ' . $url . PHP_EOL, FILE_APPEND);

        $res = curl_get($url);
        if ($res === false || $res != 'success') {
            file_put_contents('server_data.txt', '通知结果:'.$res . PHP_EOL, FILE_APPEND);

            return false;
        }

        return true;
    }

    /**
     * 充值活动
     * @param $userid
     * @param $total_price
     * @param $Billing_point
     * @return string json
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     */
    protected function Recharge_wins_big_gifts($userid, $total_price, $Billing_point)
    {
        $total_price = (int)$total_price;
        $userid = (string)$userid;
        $activity = new SysActivityInfo();
        $arr = $activity->where('Charge', 1)->select();
        $data_info = array();
        foreach ($arr as $k => $v) {
            $start = strtotime($v['StartTime']);
            $end = strtotime($v['EndTime']) + 24 * 3600;
            if (time() > $start && time() < $end) {
                $row['ActivityID'] = $v['ActivityID'];
                $row['Clear'] = $v['Clear'];
                $row['StartTime'] = $v['StartTime'];
                $row['EndTime'] = $v['EndTime'];
                $row['Type'] = $v['Type'];
                $data_info[] = $row;
            }
        }
        foreach ($data_info as $k => $v) {
            $Clear = $v['Clear'];
            $ActivityID = $v['ActivityID'];
            if ($Clear == 1) {
                $time = date("Ymd", time());
                if ($v['Type'] != 1) {
                    /*  3001 充值送豪礼   3002  充值狂欢节  3003  打鱼狂欢节  3004  神器降世 */
                    $this->activity_recharge_hash($ActivityID, $userid, $total_price, $time, $Billing_point);
                } else {
                    $this->activity_recharge_zset($ActivityID, $userid, $total_price, $time, $Billing_point);
                }
            } else {
                $start = strtotime($v['StartTime']);
                $time = date("Ymd", $start);
                if ($v['Type'] != 1) {
                    $this->activity_recharge_hash($ActivityID, $userid, $total_price, $time, $Billing_point);
                } else {
                    $this->activity_recharge_zset($ActivityID, $userid, $total_price, $time, $Billing_point);
                }
            }
        }
    }

    /* 活动redis hash类型 */
    protected function activity_recharge_hash($ActivityID, $userid, $total_price, $time, $Billing_point)
    {
        $redis = new \Redis();
        $redis->connect(config('REDIS_FORMAL.host'), config('REDIS_FORMAL.port'));
        $redis->auth(config('REDIS_FORMAL.auth'));
        $redis->select(config('REDIS_FORMAL.dbindex'));
        $TotalRecharge = $this->player_select['TotalRecharge'];
        /*累计充值*/
        $total_recharge = $total_price + $TotalRecharge;
        switch ($ActivityID) {
            case 3001:
                $res = $redis->hget('activity_' . $ActivityID . '_' . $time, $userid);
                if ($res) {
                    $score = $res + $total_price;
                    $redis->hset('activity_' . $ActivityID . '_' . $time, $userid, $score);
                } else {
                    $redis->hset('activity_' . $ActivityID . '_' . $time, $userid, $total_price);
                }
                break;
            case 3002:
                if (!in_array($Billing_point, config('CARNIVA_RECHARGE')) && $total_recharge >= 6) {
                    $res = $redis->hget('activity_' . $ActivityID . '_' . $time, $userid);
                    if ($res) {
                        $score = $res + $total_price;
                        $redis->hset('activity_' . $ActivityID . '_' . $time, $userid, $score);
                    } else {
                        $redis->hset('activity_' . $ActivityID . '_' . $time, $userid, $total_price);
                    }
                }
                break;
            case 3005:
                $res = $redis->hget('activity_' . $ActivityID . '_' . $time, $userid);
                if ($res) {
                    $score = $res + $total_price;
                    $redis->hset('activity_' . $ActivityID . '_' . $time, $userid, $score);
                } else {
                    $redis->hset('activity_' . $ActivityID . '_' . $time, $userid, $total_price);
                }
                break;
            case 3004:
                $res = $redis->hget('activity_' . $ActivityID . '_' . $time, $userid);
                if ($res) {
                    $score = $res + $total_price;
                    $redis->hset('activity_' . $ActivityID . '_' . $time, $userid, $score);
                } else {
                    $redis->hset('activity_' . $ActivityID . '_' . $time, $userid, $total_price);
                }
                break;
        }
    }

    /* 活动redis 有序集合类型 zset 类型 */
    protected function activity_recharge_zset($ActivityID, $userid, $total_price, $time, $Billing_point)
    {
        $redis = new \Redis();
        $redis->connect(config('REDIS_FORMAL.host'), config('REDIS_FORMAL.port'));
        $redis->auth(config('REDIS_FORMAL.auth'));
        $redis->select(config('REDIS_FORMAL.dbindex'));
        $TotalRecharge = $this->player_select['TotalRecharge'];
        /*累计充值*/
        $total_recharge = $total_price + $TotalRecharge;
        switch ($ActivityID) {
            case 3001:
                $res = $redis->zScore('activity_' . $ActivityID . '_' . $time, $userid);
                if ($res) {
                    $score = $res + $total_price;
                    $redis->zAdd('activity_' . $ActivityID . '_' . $time, $score, $userid);
                } else {
                    $redis->zAdd('activity_' . $ActivityID . '_' . $time, $total_price, $userid);
                }
                break;
            case 3002:
                if (!in_array($Billing_point, config('CARNIVA_RECHARGE')) && $total_recharge >= 6) {
                    $res = $redis->hget('activity_' . $ActivityID . '_' . $time, $userid);
                    if ($res) {
                        $score = $res + $total_price;
                        $redis->hset('activity_' . $ActivityID . '_' . $time, $userid, $score);
                    } else {
                        $redis->hset('activity_' . $ActivityID . '_' . $time, $userid, $total_price);
                    }
                }
                break;
            case 3005:
                $res = $redis->zScore('activity_' . $ActivityID . '_' . $time, $userid);
                if ($res) {
                    $score = $res + $total_price;
                    $redis->zAdd('activity_' . $ActivityID . '_' . $time, $score, $userid);
                } else {
                    $redis->zAdd('activity_' . $ActivityID . '_' . $time, $total_price, $userid);
                }
                break;
            case 3004:
                $res = $redis->zScore('activity_' . $ActivityID . '_' . $time, $userid);
                if ($res) {
                    $score = $res + $total_price;
                    $redis->zAdd('activity_' . $ActivityID . '_' . $time, $score, $userid);
                } else {
                    $redis->zAdd('activity_' . $ActivityID . '_' . $time, $total_price, $userid);
                }
                break;
        }
    }

    /**
     * 充值活动
     * @param $userid
     * @param $total_price
     * @return array
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     */
    protected function Recharge_item_recharge_activity($userid, $total_price)
    {
        $arr = (new SysActivityInfo())->where('Charge', 1)->select();

        $prop = [];

        foreach ($arr as $v) {
            $start = strtotime($v['StartTime']);
            $end = strtotime($v['EndTime']) + 24 * 3600;
            if (time() > $start && time() < $end) {

                $ActivityID = $v['ActivityID'];
                if (in_array($ActivityID, config('ITEM_RECHARGE_ACTIVITY'))) {
                    $counts = intval(floor($total_price / 10));
                    if ($counts >= 1) {
                        $this->Gift_props($userid, 10126, $counts, 100);
                        $this->Recharge_prop_log($userid, 10126, $counts);
                        array_push($prop, [10126, $counts, 0]);
                    }
                }

                if ($ActivityID == '3005') {
                    $counts = intval(floor($total_price / 5));
                    if ($counts >= 1) {
                        $this->Gift_props($userid, 10106, $counts, 100);
                        $this->Recharge_prop_log($userid, 10106, $counts);
                        array_push($prop, [10106, $counts, 0]);
                    }
                }
            }
        }

        return $prop;
    }

    /**
     * 充值道具日志记录
     * @param $UserID
     * @param $PropID
     * @param int $VarCounts
     * @return string json
     */
    protected function Recharge_prop_log($UserID, $PropID, $VarCounts = 0)
    {
        $Counts = (new UserPropsInfo())->where('UserID', $UserID)->where('PropID', $PropID)->value('Counts');
        $data['UserID'] = $UserID;
        $data['ServerID'] = 0;
        $data['GameName'] = '充值';
        $data['GameLevel'] = 0;
        $data['PropID'] = $PropID;
        $data['Counts'] = $Counts;
        $data['VarCounts'] = $VarCounts;
        $data['Type'] = '游戏充值';
        $data['RecordTime'] = date('Y-m-d H:i:s', time());
        UserPropLog::create($data);

        return true;
    }


    /*活动道具*/
    protected function Gift_props($UserID, $PropID, $Counts, $type = 1)
    {
        $data['UserID'] = $UserID;
        $data['PropID'] = $PropID;
        $data['Counts'] = $Counts;
        $data['Type'] = $type;
        $data['InserTime'] = date('Y-m-d H:i:s');
        $user_props_info = new UserPropsInfo();
        $res = $user_props_info->where('PropID', $PropID)->where('UserID', $UserID)->find();
        if ($res) {
            // 如果原来不是永久 就把其更新为永久
            $user_props_info->where('PropID', $PropID)->where('UserID', $UserID)->update(['ExpireTime' => '2099-01-01 00:00:00']);
            $re = $user_props_info->where('PropID', $PropID)->where('UserID', $UserID)->setInc('Counts', $Counts);
            if ($re) return true;
        } else {
            $re = $user_props_info->insert($data);
            if ($re) return true;
        }

        return false;
    }

    protected function Recharge_score_log()
    {

        $data['UserID'] = $this->player_select['UserID'];
        $data['SpreaderID'] = 0;
        $data['ServerID'] = 0;
        $data['GameName'] = '充值';
        $data['GameLevel'] = 0;
        $data['Type'] = '游戏充值';
        $data['Score'] = $this->player_select['Score'];
        $data['Lottery'] = $this->player_select['Lottery'];
        $data['Stock'] = $this->player_select['LotteryStock'];
        $data['Diamond'] = $this->player_select['Diamond'];
        // $data['SMoney'] = $arr['SMoney'];
        $data['VarScore'] = 0;
        $data['VarLottery'] = 0;
        $data['VarStock'] = 0;
        $data['VarDiamond'] = 0;
        $data['RecordTime'] = date('Y-m-d H:i:s', time());
        UserScoreLog::create($data);

        return true;
    }

}
